#region Imported Namespaces


using System;
using System.Collections.Generic;


#endregion


namespace WtfManager.Framework
{
  ///<summary>
  /// A base class for Framework functionality modules.
  ///</summary>
  public abstract class Module: FrameworkComponent
  {
    #region Fields


    private readonly ServicesCollection _services = new ServicesCollection();


    #endregion


    #region Properties/Indexers


    /// <summary>
    /// Gets a list of module <see cref="Service">services</see>
    /// </summary>
    public ReadOnlyServicesCollection Services
    {
      get
      {
        return new ReadOnlyServicesCollection(_services);
      }
    }


    #endregion


    #region Methods


    protected override sealed FrameworkComponentState LoadComponent()
    {
      List<Service> components = GetModuleServices();

      foreach (Service component in components)
      {
        AddService(component);

        component.Load();
      }

      return FrameworkComponentState.Loaded;
    }


    protected abstract List<Service> GetModuleServices();


    protected override sealed void OnUnload()
    {
      foreach (Service service in _services)
      {
        if (service.IsLoaded)
        {
          service.Unload();
        }
      }
    }


    protected override sealed void OnStateChnaged()
    {
    }


    protected override sealed FrameworkComponentState InitializeComponent()
    {
      InitializeServicesAndExtensions();

      return FrameworkComponentState.Initialized;
    }


    private void InitializeServicesAndExtensions()
    {
      foreach (Service service in _services)
      {
        if (service.State != FrameworkComponentState.Error && !service.IsInitializing && !service.IsInitialized)
        {
          service.Initialize();
        }
      }
    }


    /// <summary>
    /// Adds module service.
    /// </summary>
    /// <exception cref="InvalidOperationException">Cannot modify services list at runtime.</exception>
    private void AddService(Service service)
    {
      if (IsLoaded)
      {
        throw new InvalidOperationException("Cannot modify services list at runtime.");
      }

      _services.Add(service);
    }


    #endregion
  }
}